package lock_helper

import (
	"gitee.com/kelvins-io/common/lock"
	"gitee.com/kelvins-io/common/random"
	"gitee.com/kelvins-io/kelvins"
	"github.com/gomodule/redigo/redis"
	"github.com/google/uuid"
	"strconv"
	"time"
)

// redis 分布式锁
type LockerRedis struct {
	key, val  string
	ttlSecond int32
}

func NewLockerRedis(key, val string, ttlSecond int32) *LockerRedis {
	if kelvins.RedisConn == nil {
		return nil
	}
	if key == "" {
		key = strconv.FormatInt(time.Now().UnixNano(), 10) + random.KrandAll(5)
	}
	if val == "" {
		xid, _ := uuid.NewUUID()
		val = xid.String()
		if val == "" {
			val = strconv.FormatInt(time.Now().UnixNano(), 10) + random.KrandAll(5)
		}
	}
	if ttlSecond <= 0 {
		ttlSecond = 30
	}
	return &LockerRedis{
		key:       key,
		val:       val,
		ttlSecond: ttlSecond,
	}
}

func (o *LockerRedis) Get() (ok bool, err error) {
	redisLock, err := lock.NewRedisLock(kelvins.RedisConn, o.key, o.val)
	if err != nil {
		return false, err
	}
	return redisLock.Set(o.ttlSecond)
}

func (o *LockerRedis) Release() (err error) {
	redisLock, err := lock.NewRedisLock(kelvins.RedisConn, o.key, o.val)
	if err != nil {
		return err
	}
	return redisLock.Release()
}

func (o *LockerRedis) Check() (exist bool, err error) {
	conn := kelvins.RedisConn.Get()
	defer conn.Close()
	// to string
	str, err := redis.String(conn.Do("GET", o.key))
	if str != "" && err != redis.ErrNil {
		return true, nil
	}
	return false, err
}
